CTDGV Example

The dataset we'll be using is

CTDGV-M parsed sample - Glider01

CTD Stream from seabird Glider01 Payload CTD instrument from Station Papa

Downloading the data

We have a toolkit, publicly available, to suppliment standard DAP and NetCDF tools to download and interact with data provided by OOI. Download the OOI toolkit from github. We can find the download endpoints by browsing the OOI site for available data products and using the download URL.


In [1]:
# Make it so notebook knows how to access ooitk from the notebook dir
import sys
import os
sys.path.append(os.path.dirname(os.getcwd()))

In [2]:
# This is the download URL, obtained from the Data Product Face Page 
erddap_url = 'http://erddap-test.oceanobservatories.org:8080/erddap/tabledap/185cb2af73054d8e862e60d19c173096.html'

In [3]:
from ooitk.session import ERDDAPSession

# Open and download the ERDDAP Data
session = ERDDAPSession(erddap_url)

# Download the NetCDF dataset and apply the following constraints on the DAP request
session.open(['sci_water_pressure!="-9999999.0"','sci_water_temp!="-9999999.0"','sci_water_cond!="-9999999.0"'])

Now that we have downloaded the dataset, we need to rearrange the values so that they're ordered by pressure instead of time, that way we can plot them in order and downsample correctly.


In [4]:
# Get pressure First
pres = session.variables['sci_water_pressure'][:]

# Sort the data by pressure so we can downsample
data_length = len(session.dimensions['row'])
pres, i_map = np.unique(pres, return_index=True)

# Get temperature and conductivity from the instrument as well, sorted by pressure
temp = session.variables['sci_water_temp'][i_map]
cond = session.variables['sci_water_cond'][i_map]

Now we compute the practical salinity with respect to depth using temperature and conductivty. The gibbs seawater toolkit has the correct PSS-1978 algorithms to compute salinity.


In [5]:
from pygsw import vectors as gsw

# Calculate the practical salinity (PSS-78)
c10 = cond * 10 # Convert S/m to mS/cm
SP = gsw.sp_from_c(c10, temp, pres)

# Calculate density, using the average location of the glider
rho = gsw.ctd_density(SP, temp, pres, 50.2059787429, -144.508854831)

We have now have the samples as well as some computed values, let's graph them!


In [9]:
from datetime import datetime
from matplotlib import ticker
def convert_time(t,p):
    '''
    Converts a given timestamp to a string
    Used to convert the timestamps along the x-axis to ISO-8601 strings
    '''
    dtg = datetime.utcfromtimestamp(t)
    return dtg.isoformat()

In [7]:
# Make the images larger
pylab.rcParams['figure.figsize'] = (10.0, 8.0)

# Number of samples on graph
n = 4096
step = data_length / n

fig = figure()
# Left Plot
ax = fig.add_subplot(131)
ax.set_autoscaley_on(False)
ax.set_xlabel('Temperature (deg_C)', fontsize=14)
ax.set_ylabel('Pressure (bar)', fontsize=14)
ax.set_ylim((-100,0))
ax.plot(temp[::step],-pres[::step], c='b')

# Center Plot
ax = plt.subplot(132)
ax.set_autoscaley_on(False)
ax.set_xlabel('Conductivity (s m-1)', fontsize=14)
#ax.set_ylabel('Pressure (bar)', fontsize=14)
ax.set_ylim((-100,0))
ax.set_xlim((2.5,4.5))
ax.plot(cond[::step], -pres[::step],c='r')

# Right Plot
ax = plt.subplot(133)
ax.set_autoscaley_on(False)
ax.set_xlabel('Practical Salinity (pss)', fontsize=14)
#ax.set_ylabel('Pressure (dbar)', fontsize=14)
ax.set_ylim((-100,0))
ax.set_xlim((30,40))
ax.plot(SP[::step], -pres[::step], c='g')

plt.show()


And now for $\rho$


In [8]:
# Make the images larger
pylab.rcParams['figure.figsize'] = (10.0, 8.0)

# Only Plot
ax = plt.subplot(111)
ax.set_autoscaley_on(False)
ax.set_xlabel('Density (kg/m)', fontsize=14)
#ax.set_ylabel('Pressure (dbar)', fontsize=14)
ax.set_ylim((-100,0))
ax.set_xlim((1020, 1040))
ax.plot(rho[::step], -pres[::step], c='g')

plt.show()


What about the profile data

Let's take a look at what depths the instrument has been


In [11]:
# Get the first 1024 timesteps
time = session.variables['time'][:1024]
depth = session.variables['sci_water_pressure'][:1024]

pylab.rcParams['figure.figsize'] = (10.0, 8.0)

ax = plt.subplot(111)
ax.set_xlabel('Time (s)', fontsize=14)
ax.set_ylabel('Pressure (bar)', fontsize=14)
ax.set_ylim((-110, 2))
ax.plot(time, -depth)
ax.get_xaxis().set_major_formatter(ticker.FuncFormatter(convert_time))
ax.set_title('Depth Profile over time')
plt.setp(plt.subplot(111).get_xticklabels(), rotation=15)

plt.show()



In [10]:
session.close()

Plotting the glider's path


In [11]:
from ooitk.session import ERDDAPSession
# Get the glider's engineering data
erddap_url = 'http://erddap-test.oceanobservatories.org:8080/erddap/tabledap/9a3dde59936345d182df2f1b2a5b859d.html'

session = ERDDAPSession(erddap_url)

In [12]:
session.open(['m_gps_lat<"90"', 'm_gps_lat>"-90"', 'm_gps_lon<"-120"'])

In [13]:
# Grab location information from the dataset
lat = session.variables['m_gps_lat'][:]
lon = session.variables['m_gps_lon'][:]

In [14]:
from mpl_toolkits.basemap import Basemap

# Plot the location/path information on a standard mercator projection
m = Basemap(projection='merc', llcrnrlat = np.min(lat)-1, urcrnrlat = np.max(lat)+1, llcrnrlon = np.min(lon)-1, urcrnrlon = np.max(lon)+1, resolution='l')
parallels = np.arange(0., 90., 10.)
m.drawparallels(parallels, labels=[1, 0, 0, 0], fontsize=10)
meridians = np.arange(180, 360., 4.)
m.drawmeridians(meridians, labels=[0,0,0,1], fontsize=10)
x, y = m(lon, lat)
plt.plot(x,y)
plt.title('Glider 001 Path')
plt.show()



In [15]:
session.close()